/**
 * 产品管理控制器
 * 
 * 该文件负责处理与产品相关的所有业务逻辑，包括：
 * - 获取产品列表（支持分页和模糊查询）
 * - 根据ID获取单个产品信息
 * - 创建新产品
 * - 更新产品信息
 * - 删除产品
 * - 批量操作
 * - 批量导入（Excel）
 * 
 * 所有接口均通过 Express 路由调用，并遵循项目统一的错误处理和响应格式规范。
 */
const { products: Product, product_categories: Category } = require('../models/init-models')(require('../db').sequelize, require('sequelize').DataTypes); // 导入产品模型和分类模型
const { formatPagination, buildLikeQuery, generatePaginationInfo } = require('../utils'); // 导入工具函数
const XLSX = require('xlsx'); // 导入xlsx库用于处理Excel文件
const fs = require('fs'); // 导入文件系统模块

/**
 * 生成产品编码
 * 格式为 CP+年月日+6位随机数字
 * @returns {string} 产品编码
 */
const generateProductCode = () => {
  const now = new Date();
  const year = String(now.getFullYear()).slice(-2); // 只取年份后两位
  const month = String(now.getMonth() + 1).padStart(2, '0');
  const day = String(now.getDate()).padStart(2, '0');
  
  // 生成6位随机数字
  const randomNum = String(Math.floor(Math.random() * 1000000)).padStart(6, '0');
  
  return `CP${year}${month}${day}${randomNum}`;
};

/**
 * 获取产品列表
 * 支持分页和模糊查询，返回数据包含分类信息
 * @param {Object} req - 请求对象
 * @param {Object} res - 响应对象
 * @returns {Promise<void>} 返回JSON格式的响应数据
 * 
 * @description
 * 该接口用于获取系统中所有的产品信息，支持分页和模糊查询。
 * 可以通过 query 参数指定 page、limit 和搜索条件。
 * 使用 Sequelize 的 findAndCountAll 方法同时获取数据和总条数。
 * 返回数据包含产品分类信息
 */
const getProductList = async (req, res) => {
    try {
        // 格式化分页参数
        const { page, limit, offset } = formatPagination(req.query);
        
        // 定义可搜索的字段
        const searchableFields = ['product_name', 'product_code', 'description', 'sku'];
        
        // 构建模糊查询条件
        const whereConditions = buildLikeQuery(req.query, searchableFields);

        // 如果有分类ID参数，则添加精确匹配条件
        if (req.query.category_id) {
            whereConditions.category_id = req.query.category_id;
        }

        // 构建查询选项
        const queryOptions = {
            limit,    // 每页条数
            offset,   // 偏移量
            include: [{ 
                model: Category, 
                as: 'category',
                attributes: ['category_id', 'category_name', 'description'] // 只选择需要的分类字段
            }] // 关联查询分类信息
        };

        // 如果有查询条件，则添加到查询选项中
        if (Object.keys(whereConditions).length > 0) {
            queryOptions.where = whereConditions;
        }

        // 使用 findAndCountAll 同时获取数据和总条数
        const result = await Product.findAndCountAll(queryOptions);

        // 生成分页信息
        const pagination = generatePaginationInfo(result.count, page, limit);

        // 使用统一的分页响应格式返回结果
        res.paginated(result.rows, pagination, '获取产品列表成功');
    } catch (err) {
        res.error('获取产品列表失败');
    }
};

/**
 * 通过ID获取单个产品信息
 * 返回数据包含分类信息
 * @param {Object} req - 请求对象
 * @param {Object} res - 响应对象
 * @returns {Promise<void>} 返回JSON格式的响应数据
 * 
 * @description
 * 该接口用于根据传入的ID获取单个产品的详细信息，包含分类信息
 * 使用 Sequelize 的 findByPk 方法进行数据库查询，并关联查询分类信息
 * 如果未找到对应记录，返回404状态码。
 */
const getProductById = async (req, res) => {
    try {
        // 从请求参数中获取产品ID
        const productId = req.params.id;
        
        // 根据ID查找产品，包含分类信息
        const product = await Product.findByPk(productId, {
            include: [{ 
                model: Category, 
                as: 'category',
                attributes: ['category_id', 'category_name', 'description'] // 只选择需要的分类字段
            }]
        });

        // 如果产品不存在，返回404错误
        if (!product) {
            return res.error('产品不存在', 1, 404);
        }

        // 返回产品信息（包含分类信息）
        res.success(product, '获取产品信息成功');
    } catch (err) {
        console.error('获取产品信息失败:', err);
        res.error('获取产品信息失败');
    }
};

/**
 * 添加新产品
 * @param {Object} req - 请求对象
 * @param {Object} res - 响应对象
 * @returns {Promise<void>} 返回JSON格式的响应数据
 * 
 * @description
 * 该接口用于创建新的产品记录，返回数据包含分类信息
 * 使用 Sequelize 的 create 方法将数据写入数据库。
 * 成功后返回新创建的记录及分类信息
 */
const addProduct = async (req, res) => {
    try {
        // 从请求体中移除 product_id 字段，让数据库自动生成
        const productData = { ...req.body };
        delete productData.product_id;
        
        // 生成产品编码
        productData.product_code = generateProductCode();
        
        // 创建新产品
        const product = await Product.create(productData);
        
        // 重新查询产品信息，包含分类信息
        const productWithCategory = await Product.findByPk(product.product_id, {
            include: [{ 
                model: Category, 
                as: 'category',
                attributes: ['category_id', 'category_name', 'description']
            }]
        });
        
        // 返回成功响应
        res.success(productWithCategory, '添加产品成功');
    } catch (err) {
        // 根据错误类型返回不同的错误信息
        if (err.name === 'SequelizeUniqueConstraintError') {
            // 检查是哪个字段违反了唯一约束
            if (err.errors && err.errors.length > 0) {
                const field = err.errors[0].path;
                if (field === 'product_name') {
                    res.error('产品名称已存在，添加失败', 1, 400);
                } else if (field === 'product_code') {
                    res.error('产品编码重复，添加失败', 1, 400);
                } else {
                    res.error('数据已存在，添加失败', 1, 400);
                }
            } else {
                res.error('产品信息已存在，添加失败', 1, 400);
            }
        } else if (err.name === 'SequelizeValidationError') {
            res.error(`数据验证失败: ${err.message}`, 1, 400);
        } else {
            res.error('添加产品失败');
        }
    }
};

/**
 * 更新产品信息
 * 返回数据包含分类信息
 * @param {Object} req - 请求对象
 * @param {Object} res - 响应对象
 * @returns {Promise<void>} 返回JSON格式的响应数据
 * 
 * @description
 * 该接口用于更新现有产品信息，返回数据包含分类信息
 * 首先通过ID查找要更新的记录，如果不存在则返回404。
 * 然后使用 Sequelize 的 update 方法更新数据库记录。
 * 
 * 注意：在更新产品名称时，会检查是否与其他产品的名称冲突。
 */
const updateProduct = async (req, res) => {
    try {
        // 从请求体或参数中获取产品ID
        const productId = req.body.product_id || req.params.id;
        
        // 先查找产品是否存在
        const existingProduct = await Product.findByPk(productId);
        if (!existingProduct) {
            // 如果产品不存在，返回404错误
            return res.error('产品不存在', 1, 404);
        }

        // 从请求体中移除 product_id 字段，避免更新主键
        const productData = { ...req.body };
        delete productData.product_id;

        // 更新产品信息
        const [updatedCount] = await Product.update(productData, {
            where: {
                product_id: productId
            }
        });

        // 重新获取更新后的产品信息，包含分类信息
        const updatedProduct = await Product.findByPk(productId, {
            include: [{ 
                model: Category, 
                as: 'category',
                attributes: ['category_id', 'category_name', 'description']
            }]
        });

        // 返回成功响应
        res.success(updatedProduct, '更新产品成功');
    } catch (err) {
        // 根据错误类型返回不同的错误信息
        if (err.name === 'SequelizeUniqueConstraintError') {
            // 检查是哪个字段违反了唯一约束
            if (err.errors && err.errors.length > 0) {
                const field = err.errors[0].path;
                if (field === 'product_name') {
                    res.error('产品名称已存在，更新失败', 1, 400);
                } else {
                    res.error('数据已存在，更新失败', 1, 400);
                }
            } else {
                res.error('产品信息已存在，更新失败', 1, 400);
            }
        } else if (err.name === 'SequelizeValidationError') {
            res.error(`数据验证失败: ${err.message}`, 1, 400);
        } else {
            res.error('更新产品失败');
        }
    }
};

/**
 * 删除产品
 * @param {Object} req - 请求对象
 * @param {Object} res - 响应对象
 * @returns {Promise<void>} 返回JSON格式的响应数据
 * 
 * @description
 * 该接口用于删除指定的产品记录。
 * 删除操作使用 Sequelize 的 destroy 方法执行。
 * 如果没有删除任何记录，说明产品不存在。
 */
const delProduct = async (req, res) => {
    try {
        // 从请求参数中获取产品ID
        const productId = req.params.id;
        
        // 删除产品
        const deletedCount = await Product.destroy({
            where: {
                product_id: productId
            }
        });
        
        // 如果没有删除任何记录，说明产品不存在
        if (deletedCount === 0) {
            return res.error('产品不存在', 1, 404);
        }
        
        // 返回成功响应
        res.success({ deletedCount }, '删除产品成功');
    } catch (err) {
        res.error('删除产品失败');
    }
};

/**
 * 批量操作产品
 * @param {Object} req - 请求对象
 * @param {Object} res - 响应对象
 * @returns {Promise<void>} 返回JSON格式的响应数据
 * 
 * @description
 * 该接口用于批量操作产品，支持批量删除、批量更新等操作。
 * 通过 action 参数指定操作类型，data 参数指定操作的数据。
 */
const batchProductOperation = async (req, res) => {
    try {
        const { action, data } = req.body;
        
        switch (action) {
            case 'delete':
                // 批量删除产品
                const deletedCount = await Product.destroy({
                    where: {
                        product_id: {
                            [require('sequelize').Op.in]: data.ids
                        }
                    }
                });
                
                res.success({ deletedCount }, '批量删除产品成功');
                break;
                
            case 'update':
                // 批量更新产品
                const updatedCount = await Product.update(data.updates, {
                    where: {
                        product_id: {
                            [require('sequelize').Op.in]: data.ids
                        }
                    }
                });
                
                res.success({ updatedCount }, '批量更新产品成功');
                break;
                
            default:
                res.error('不支持的操作类型');
        }
    } catch (err) {
        console.error('批量操作产品失败:', err);
        res.error('批量操作产品失败');
    }
};

/**
 * 从Excel文件导入产品数据
 * @param {Object} req - 请求对象
 * @param {Object} res - 响应对象
 * @returns {Promise<void>} 返回JSON格式的响应数据
 * 
 * @description
 * 该接口用于从Excel文件导入产品数据。
 * 解析Excel文件，将数据转换为产品对象，然后批量创建产品。
 */
const importProducts = async (req, res) => {
    try {
        // 检查是否有上传文件
        if (!req.file) {
            return res.error('请上传Excel文件', 1, 400);
        }

        // 读取上传的Excel文件
        const workbook = XLSX.readFile(req.file.path);
        
        // 获取第一个工作表
        const sheetName = workbook.SheetNames[0];
        const worksheet = workbook.Sheets[sheetName];
        
        // 将工作表转换为JSON数据
        const jsonData = XLSX.utils.sheet_to_json(worksheet);
        
        // 检查是否有数据
        if (!jsonData || jsonData.length === 0) {
            // 删除上传的文件
            fs.unlinkSync(req.file.path);
            return res.error('Excel文件中没有数据', 1, 400);
        }

        // 转换数据格式并验证必填字段
        const productsData = jsonData.map((row, index) => {
            // 检查必填字段
            if (!row['产品名称']) {
                throw new Error(`第${index + 2}行产品名称不能为空`);
            }
            
            if (!row['产品分类ID'] && !row['产品分类名称']) {
                throw new Error(`第${index + 2}行产品分类ID或分类名称必须填写一个`);
            }
            
            // 转换数据格式
            return {
                product_name: row['产品名称'],
                cost_price: row['成本价'] ? parseFloat(row['成本价']) : 0,
                retail_price: row['零售价'] ? parseFloat(row['零售价']) : 0,
                wholesale_price: row['批发价'] ? parseFloat(row['批发价']) : 0,
                category_id: row['产品分类ID'] ? parseInt(row['产品分类ID']) : null,
                specifications: row['产品规格'] || '',
                // 自动生成产品编码
                product_code: generateProductCode(),
                // 如果没有提供分类ID，但提供了分类名称，需要在后续处理中查找分类ID
                category_name: row['产品分类名称'] || ''
            };
        });

        // 处理分类名称到分类ID的转换
        for (let i = 0; i < productsData.length; i++) {
            const product = productsData[i];
            // 如果提供了分类名称但没有分类ID，则尝试根据名称查找分类
            if (product.category_name && !product.category_id) {
                const category = await Category.findOne({
                    where: {
                        category_name: product.category_name
                    }
                });
                
                if (category) {
                    product.category_id = category.category_id;
                } else {
                    throw new Error(`找不到名称为"${product.category_name}"的产品分类`);
                }
            }
            
            // 清除临时的分类名称字段
            delete product.category_name;
        }

        // 批量创建产品
        const createdProducts = await Product.bulkCreate(productsData, {
            validate: true, // 启用验证
            returning: true // 返回创建的记录
        });

        // 删除上传的文件
        fs.unlinkSync(req.file.path);

        // 返回成功响应
        res.success({
            importedCount: createdProducts.length,
            products: createdProducts
        }, `成功导入${createdProducts.length}个产品`);
    } catch (err) {
        console.error('导入产品失败:', err);
        
        // 删除上传的文件（如果存在）
        if (req.file && req.file.path && fs.existsSync(req.file.path)) {
            fs.unlinkSync(req.file.path);
        }
        
        // 根据错误类型返回不同的错误信息
        if (err.name === 'SequelizeUniqueConstraintError') {
            res.error(`数据重复：${err.message}`, 1, 400);
        } else if (err.name === 'SequelizeValidationError') {
            res.error(`数据验证失败: ${err.message}`, 1, 400);
        } else {
            res.error(err.message || '导入产品失败');
        }
    }
};

// 导出所有路由处理函数
module.exports = {
    getProductById,           // 获取单个产品信息
    getProductList,           // 获取产品列表
    addProduct,               // 添加新产品
    updateProduct,            // 更新产品信息
    delProduct,               // 删除产品
    batchProductOperation,    // 批量操作产品
    importProducts            // 从Excel导入产品
};